define(['app', 'json2', 'clipboard', 'zTree-exhide', 'ace-language-tools'], function(app, JSON2, Clipboard) {
    app.controller('MockEditorController', function($scope, $compile, $http, $location, $timeout, $cookies,
            $routeParams, xDialog) {
        var self = this;

        self.module = $routeParams.module;
        self.fullPath = '/' + self.module + '/' + $routeParams.path;
        var hasPath = $routeParams.path ? true : false;

        self.fullScreen = false;
        self.fontSize = 12;
        var jsonEditor = null;

        self.state = { changed: false, enabled: false };
        self.textMock = '';

        var zTreeObj = null;
        var selectedNode = null;
        self.filter = '';
        self.node = { parent: '', name: '', root: false, leaf: false };

        var newCount = 1;
        var setting = {
            view: {
                selectedMulti: false,
                dblClickExpand: false,
                addHoverDom: function(treeId, treeNode) {
                    if (treeNode.editNameFlag || treeNode.leaf || jQuery('#addBtn_' + treeNode.tId).length > 0) {
                        return;
                    }
                    var sObj = jQuery('#' + treeNode.tId + '_span');
                    var addElement = '<span class="button add" id="addBtn_' + treeNode.tId
                            + '" title="新建" onfocus="this.blur();"></span>';
                    sObj.after(addElement);
                    var btnAdd = jQuery('#addBtn_' + treeNode.tId);
                    if (btnAdd) {
                        btnAdd.bind('click', function() {
                            treeNode.parent = getParentPath(treeNode);
                            xDialog.open().addMock({
                                module: self.module,
                                treeId: treeId,
                                treeNode: treeNode
                            }).then(function(node) {
                                var nodes = jQuery.fn.zTree.getZTreeObj('mock-tree').addNodes(treeNode, {
                                    id: (100 + newCount),
                                    pId: treeNode.id,
                                    name: node.name,
                                    leaf: node.leaf
                                });
                                zTreeObj.selectNode(nodes[0]);
                                jQuery('#' + nodes[0].tId + '>a').trigger('click');
                            });
                            return false;
                        });
                    }
                },
                removeHoverDom: function(treeId, treeNode) {
                    jQuery('#addBtn_' + treeNode.tId).unbind().remove();
                }
            },
            data: {
                simpleData: {
                    enable: false
                }
            },
            edit: {
                enable: true,
                removeTitle: '删除',
                renameTitle: '重命名',
                showRemoveBtn: function(treeId, treeNode) {
                    return !treeNode.root;
                },
                showRenameBtn: function(treeId, treeNode) {
                    return !treeNode.root;
                }
            },
            callback: {
                beforeDrag: function() {
                    return false;
                },
                beforeEditName: function(treeId, treeNode) {
                    treeNode.oldName = treeNode.name;
                    return true;
                },
                beforeRemove: function(treeId, treeNode) {
                    var path = getParentPath(treeNode) + '/' + treeNode.name;
                    xDialog.confirm('确认信息', '您确定要删除【' + path + '】吗？').then(function(yes) {
                        if (yes) {
                            $http.post('/mock/data/delete', {
                                module: self.module,
                                path: path
                            }).then(function(response) {
                                if (response.data) {
                                    jQuery.fn.zTree.getZTreeObj('mock-tree').removeNode(treeNode);
                                    var nodePath = self.node.parent + '/' + self.node.name;
                                    if ((new RegExp('^' + path)).test(nodePath)) {
                                        self.node.parent = '';
                                        self.node.name = '';
                                        self.textMock = '';
                                    }
                                }
                            });
                        }
                    });
                    return false;
                },
                onClick: function(event, treeId, treeNode) {
                    selectedNode = treeNode;
                    self.node.parent = getParentPath(selectedNode);
                    self.node.name = treeNode.name;
                    self.node.leaf = treeNode.leaf;
                    self.node.root = treeNode.root;
                    var path = getNodePath(self.node);
                    jQuery('#file-url').attr('href', path);
                    if (!hasPath) {
                        $location.path('/mock-module' + path, false).replace();
                    }
                    hasPath = false;

                    if (self.node.leaf) {
                        $http({
                            method: 'POST',
                            url: path + '?origin',
                            transformResponse: function(response) {
                                return response;
                            }
                        }).then(function(response) {
                            self.state.changed = false;
                            self.state.enabled = true;
                            self.textMock = JSON2.format(response.data, '\t');

                            jsonEditor.setValue(self.textMock, -1);
                            jsonEditor.resize();
                            jsonEditor.focus();
                            if (response.data == '{}') {
                                jsonEditor.execCommand('comment.header');
                            } else {
                                self.gotoTop();
                            }
                        });
                    } else {
                        self.state.changed = false;
                        self.state.enabled = false;
                        self.textMock = '';
                        $timeout(function() { $scope.$apply(); });
                    }
                },
                onRename: function(event, treeId, treeNode) {
                    if (treeNode.name != treeNode.oldName) {
                        var parent = getParentPath(treeNode);
                        $http.post('/mock/data/rename', {
                            module: self.module,
                            oldPath: parent + '/' + treeNode.oldName,
                            newPath: parent + '/' + treeNode.name
                        }).then(function(response) {
                            if(response.data) {
                                // update file url
                                if (selectedNode) {
                                    self.node.parent = getParentPath(selectedNode);
                                    self.node.name = selectedNode.name;
                                    jQuery('#file-url').attr('href', getNodePath(self.node));
                                }
                            } else {
                                // reset tree node name
                                treeNode.name = treeNode.oldName;
                                zTreeObj.updateNode(treeNode);
                                if (treeNode.leaf) {
                                    xDialog.alert('提示信息', '您重命名的文件已存在，请更改为其它名称！');
                                } else {
                                    xDialog.alert('提示信息', '您重命名的文件夹已存在，请更改为其它名称！');
                                }
                            }
                        });
                    }
                }
            }
        };

        self.init = function() {
            new Clipboard('#copy', {
                text: function() {
                    return jsonEditor.getValue();
                }
            });

            // json editor
            jsonEditor = ace.edit('json-editor');
            jsonEditor.getSession().setMode("ace/mode/hjson");
            jsonEditor.setOptions({
                fontSize: self.fontSize,
                //maxPixelHeight: 1024,
                showPrintMargin: false,
                autoScrollEditorIntoView: true,
                enableBasicAutocompletion: true,
                enableSnippets: true,
                enableLiveAutocompletion: true,
            });
            jsonEditor.on('change', function(e) {
                var newValue = jsonEditor.getValue();
                if (newValue !== '' && newValue !== self.textMock) {
                    self.state.changed = true;
                } else {
                    self.state.changed = false;
                }
                // apply scope queue
                $timeout(function() { $scope.$apply(); });
            });
            // find and replace
            jsonEditor.commands.addCommand({
                name: 'find-replace',
                bindKey: { win: 'Ctrl-F', mac: 'Command-F'},
                exec: function(editor) {
                    self.showSearchbox();
                }
            });
            // add comment
            var templates = {
                'header': _.template('/**\n标题：<%=title%>\nURL：<%=url%>\nMethod：post\n入参：{}\n出参：\n*/\n'),
                'line': _.template('/*<%=data%>*/')
            };
            jsonEditor.commands.addCommand({
                name: 'comment.header',
                bindKey: { win: 'Ctrl-H', mac: 'Command-H'},
                exec: function(editor) {
                    var url = jQuery('#file-url').attr('href');
                    url = url.replace(new RegExp('^/' + self.module + '|.json$', 'gi'), '');
                    editor.gotoLine(1);
                    editor.insert(templates['header']({
                        title: '',
                        url: url
                    }));
                    editor.moveCursorTo(1, 3);
                }
            });
            jsonEditor.commands.addCommand({
                name: 'comment.line',
                bindKey: { win: 'Ctrl-/', mac: 'Command-/'},
                exec: function(editor) {
                    var cursor = editor.selection.getCursor();
                    editor.insert(templates['line']({
                        data: ''
                    }));
                    editor.moveCursorTo(cursor.row, cursor.column + 2);
                }
            });
            // format code
            var formattedCode = '';
            jsonEditor.commands.addCommand({
                name: 'format',
                bindKey: { win: 'Ctrl-Shift-F', mac: 'Command-Option-F'},
                exec: function(editor) {
                    if (editor.getValue() != formattedCode) {
                        formattedCode = JSON2.format(editor.getValue(), '\t');
                        editor.setValue(formattedCode, -1);
                        editor.resize();
                    }
                }
            });
            // goto line
            jsonEditor.commands.addCommand({
                name: 'goto',
                bindKey: { win: 'Ctrl-L', mac: 'Command-L'},
                exec: function(editor) {
                    xDialog.open().showGotoLine({
                        maxLine: editor.session.getLength()
                    }).then(function(line) {
                        editor.gotoLine(line);
                    });
                }
            });
            // save
            jsonEditor.commands.addCommand({
                name: 'save',
                bindKey: { win: 'Ctrl-S', mac: 'Command-S'},
                exec: function(editor) {
                    if (self.state.enabled && self.state.changed) {
                        self.save();
                    }
                }
            });
            jsonEditor.getSession().on('changeScrollTop', function(scrollTop) {
                if (scrollTop > 32) {
                    jQuery('.x-editor-tool.x-goto-top').removeClass('hidden');
                } else {
                    jQuery('.x-editor-tool.x-goto-top').addClass('hidden');
                }
            });
            // json editor tools
            jQuery('#json-editor .ace_scroller').append($compile(jQuery('#editor-tools').html())($scope));
            jQuery('.x-editor-tool').mousedown(function(e) { return false; });
            // full screen
            $scope.$watch('vm.fullScreen', function() {
                setTimeout(function() {
                    jsonEditor.setOption('maxPixelHeight', jQuery('.x-editor').parents('.x-page-scope').height());
                    jsonEditor.resize();
                }, 50);
            });

            // load tree nodes
            loadTreeNodes();

            // ztree filter scroller
            jQuery('.x-tree').parents('.x-page-scope').scroll(function() {
                jQuery(this).find('.x-tree-filter').css('top', this.scrollTop + 'px')
                    .css('left', this.scrollLeft + 'px');
            });
        }

        self.collapseAll = function() {
            zTreeObj.expandAll(false);
        }

        self.expandAll = function() {
            zTreeObj.expandAll(true);
        }

        self.refresh = function() {
            loadTreeNodes();
        }

        function loadTreeNodes() {
            self.textMock = '';
            self.state.changed = false;
            self.state.enabled = false;
  
            self.filter = '';
            self.node.parent = '';
            self.node.name = '';
            self.node.root = false;
            self.node.leaf = false;
            
            jQuery.fn.zTree.destroy('mock-tree');
            $http.post('/mock/data/tree', { module: self.module }).then(function(response) {
                zTreeObj = jQuery.fn.zTree.init(jQuery('#mock-tree'), setting, response.data);
                if (!_.isEmpty(self.fullPath)) {
                    var nodes = zTreeObj.getNodesByFilter(function(node) {
                        node.parent = getParentPath(node);
                        if(getNodePath(node)  == self.fullPath) {
                            return true;
                        }
                        return false;
                    });
                    if (nodes != null && nodes.length > 0) {
                        zTreeObj.selectNode(nodes[0]);
                        zTreeObj.expandNode(nodes[0], true, false, false);
                        jQuery('#' + nodes[0].tId + '>a').trigger('click');
                    }
                    self.fullPath = '';
                }
            });
        }

        function getParentPath(node) {
            var paths = node.getPath();
            var parent = '';
            for (var i = 1; i < paths.length - 1; i++) {
                parent += '/' + paths[i].name;
            }
            return parent;
        }

        function getNodePath(node) {
            var path = '/' + self.module + node.parent + '/' + node.name;
            if (!node.leaf) {
                path = (node.root ? '/' + self.module : path) + '/';
            }
            return path;
        }

        self.save = function() {
            xDialog.confirm('确认信息', '您确定要保存文件【' + self.node.name + '】的数据吗？').then(function(yes) {
                if (yes) {
                    $http.post('/mock/data/save', {
                        module: self.module,
                        type: 'file',
                        folder: self.node.parent,
                        file: self.node.name,
                        data: JSON2.minify(jsonEditor.getValue())
                    }).then(function(response) {
                        if (response.data) {
                            self.state.changed = false;
                            self.textMock = jsonEditor.getValue();
                        }
                    });
                }
            });
        }

        var showNodes = [];
        self.filterTree = function() {
            var allNode = zTreeObj.transformToArray(zTreeObj.getNodes());
            zTreeObj.hideNodes(allNode);
            if (self.filter == '') {
                zTreeObj.showNodes(allNode);
                zTreeObj.expandAll(true);
            } else {
                showNodes = zTreeObj.getNodesByFilter(function(node) {
                    if(node.name.indexOf(self.filter) != -1) {
                        return true;
                    }
                    return false;
                });
                showNodes = zTreeObj.transformToArray(showNodes);
                for (var node in showNodes) {
                    if (showNodes.hasOwnProperty(node)) {
                        findParentNode(zTreeObj, showNodes[node]);
                    }
                }
                zTreeObj.showNodes(showNodes);
            }
        }

        function findParentNode(treeObj, node) {
            treeObj.expandNode(node, true, false, false);
            var parentNode = node.getParentNode();
            if (parentNode != null) {
                showNodes.push(parentNode);
                findParentNode(treeObj, parentNode);
            }
        }

        self.copyMock = function(type) {
            xDialog.open().copyMock({
                type: type,
                module: self.module,
                node: self.node
            }).then(function(data) {
                self.fullPath = '/' + self.module + data.path;
                loadTreeNodes();
            });
        }

        self.setFontSize = function(size) {
            self.fontSize = size;
            jsonEditor.setFontSize(size);
        }

        // show searchbox
        var searchContext = $cookies.getObject('search_context');
        if (_.isEmpty(searchContext)) {
            searchContext = {
                needle: '',
                replace: '',
                backwards: false,
                wrap: false,
                caseSensitive: false,
                wholeWord: false,
                range: null,
                regExp: false
            };
        }
        self.searchboxClosed = true;
        self.showSearchbox = function() {
            if (self.searchboxClosed) {
                self.searchboxClosed = false;
                xDialog.open().showSearchbox({
                    editor: jsonEditor,
                    context: searchContext
                }).then(function(closed) {
                    self.searchboxClosed = true;
                    $cookies.putObject('search_context', searchContext);
                }, function(cancelled) {
                    self.searchboxClosed = true;
                });
            }
        }
        // show shortcut key
        self.showShortcutKey = function() {
            xDialog.open().showShortcutKey();
        }
        // goto top of editor
        self.gotoTop = function() {
            jsonEditor.scrollToLine(0);
        }

        // show mock test
        var host = $cookies.get('host');
        if (_.isEmpty(host)) {
            host = 'http://127.0.0.1:8080';
        }
        self.showTest = function() {
            var path = jQuery('#file-url').attr('href');
            path = path.replace(new RegExp('^/' + self.module + '|.json$', 'gi'), '');
            xDialog.open().testMock({
                host: host,
                path: path
            }).then(function(result) {
                if (result.host != null) {
                    host = result.host;
                    $cookies.put('host', host);
                }
            });
        }
    });
});
